;;; $Id: console.sld 405 2014-03-06 04:33:08Z alan.watson.f $

(define-library (oaxaca console)

  (export display-status)

  (import (scheme base)
          (scheme inexact)
          (scheme write)
          (scheme process-context))

  (import (oaxaca file)
          (oaxaca finder)
          (oaxaca housekeeping)
          (oaxaca instrument)
          (oaxaca lamp)
          (oaxaca thread)
          (oaxaca wfc)
          (oaxaca wfs))

  (begin

    (define (display-key-value key value . rest)
      (display "<tr><td>")
      (display key)
      (display "</td><td>")
      (display value)
      (for-each
       (lambda (value)
         (display #\space)
         (display value))
       rest)
      (display "</td></tr>\n"))

    (define (vector-rms v)
      (if (zero? (vector-length v))
        0
        (sqrt (/ (apply + (vector->list (vector-map (lambda (x) (* x x)) v)))
                 (vector-length v)))))

    (define (number->decimal x w p sign?)
      (define (string-pad-left s w c)
        (if (> (string-length s) w)
          s
          (string-append (make-string (- w (string-length s)) c) s)))
      (let* ((i (exact (floor (abs x))))
             (f (- (abs x) i))
             (f (exact (round (* f (expt 10 p)))))
             (i (if (= f (expt 10 p)) (+ i 1) i))
             (f (if (= f (expt 10 p)) 0 f))
             (s (if (zero? p)
                  (number->string i)
                  (string-append (number->string i)
                                 "."
                                 (string-pad-left (number->string f) p #\0))))
             (s (cond
                 ((negative? x) (string-append "&minus;" s))
                 (sign? (string-append "+" s))
                 (else s)))
             (s (if w (string-pad-left s w #\space) s)))
        s))

    (define (emph-if-saturated x s)
      (if (or (>= x +1) (<= x -1))
        (string-append "<emph class=\"saturated\">" s "</emph>")
        s))

    (define (display-detector-details window
                                      pixel-frequency
                                      min-frame-frequency
                                      max-frame-frequency
                                      frame-frequency
                                      actual-frame-frequency
                                      frame-time
                                      integration-time
                                      exposure-time
                                      frame
                                      frames-per-integration
                                      integration
                                      integrations-per-exposure
                                      z-min
                                      z-max
                                      z-mean
                                      fwhm
                                      eshm
                                      spatial-sigma
                                      temporal-sigma
                                      ds-mean-vector
                                      ds-sigma-vector)
      (apply display-key-value "Window" window)
      (display-key-value "Pixel Frequency"
                         (string-append (number->decimal (/ pixel-frequency 1e6) #f 1 #f)
                                        " MHz"))
      (display-key-value "Minimum Frame Frequency"
                         (string-append (number->decimal min-frame-frequency #f 2 #f)
                                        " Hz"))
      (display-key-value "Maximum Frame Frequency"
                         (string-append (number->decimal max-frame-frequency #f 2 #f)
                                        " Hz"))
      (display-key-value "Frame Frequency"
                         (string-append (number->decimal frame-frequency #f 2 #f)
                                        " Hz"))
      (display-key-value "Actual Frame Frequency"
                         (string-append (number->decimal actual-frame-frequency #f 2 #f)
                                        " Hz"))
      (display-key-value "Frame Time"
                         (string-append (number->decimal frame-time #f 6 #f)
                                        " s"))
      (display-key-value "Integration Time"
                         (string-append (number->decimal integration-time #f 6 #f)
                                        " s"))
      (display-key-value "Exposure Time"
                         (string-append (number->decimal exposure-time #f 6 #f)
                                        " s"))
      (if (zero? frames-per-integration)
        (display-key-value "Frame"
                           frame)
        (display-key-value "Frame"
                           frame "of" frames-per-integration))
      (if (zero? integrations-per-exposure)
        (display-key-value "Integration"
                           integration)
        (display-key-value "Integration"
                           integration "of" integrations-per-exposure))
      (display-key-value "Min/Mean/Max" (number->decimal z-min #f 0 #t) (number->decimal z-mean #f 0 #t) (number->decimal z-max #f 0 #t))
      (when (and fwhm eshm)
        (display-key-value "FWHM/ESHM" (number->decimal fwhm #f 1 #f) (number->decimal eshm #f 0 #f)))
      (display-key-value "Spatial Sigma" (string-append (number->decimal spatial-sigma #f 1 #f) " DN"))
      (display-key-value "Temporal Sigma" (string-append (number->decimal temporal-sigma #f 1 #f) " DN"))
      (display-key-value "RMS Error Mean"
                         (string-append (number->decimal (vector-rms ds-mean-vector) #f 2 #f)
                                        " pixel"))
      (display-key-value "RMS Error Sigma"
                         (string-append (number->decimal (vector-rms ds-sigma-vector) #f 2 #f)
                                        " pixel")))

    (define (display-detector-summary window
                                      pixel-frequency
                                      frame-frequency
                                      actual-frame-frequency
                                      frame-time
                                      integration-time
                                      exposure-time
                                      frame
                                      frames-per-integration
                                      integration
                                      integrations-per-exposure
                                      z-min
                                      z-max
                                      z-mean
                                      fwhm
                                      eshm
                                      spatial-sigma
                                      temporal-sigma
                                      ds-mean-vector
                                      ds-sigma-vector
                                      g-vector)
      (display-key-value "Frame Frequency"
                         (string-append (number->decimal frame-frequency #f 2 #f))
                         " Hz")
      (display-key-value "Integration Time"
                         (string-append (number->decimal integration-time #f 3 #f))
                         " s")
      (display-key-value "Exposure Time"
                         (string-append (number->decimal exposure-time #f 3 #f))
                         " s")
      (if (zero? frames-per-integration)
        (display-key-value "Frame"
                           frame)
        (display-key-value "Frame"
                           frame "of" frames-per-integration))
      (if (zero? integrations-per-exposure)
        (display-key-value "Integration"
                           integration)
        (display-key-value "Integration"
                           integration "of" integrations-per-exposure))

      (display-key-value "Min/Mean/Max" (number->decimal z-min #f 0 #t) (number->decimal z-mean #f 0 #t) (number->decimal z-max #f 0 #t))
      (when (and fwhm eshm)
        (display-key-value "FWHM/ESHM" (number->decimal fwhm #f 1 #f) (number->decimal eshm #f 0 #f)))
      (display-key-value "RMS Error Mean"
                         (string-append (number->decimal (vector-rms ds-mean-vector) #f 2 #f)
                                        " pixel"))
      (display-key-value "RMS Error Sigma"
                         (string-append (number->decimal (vector-rms ds-sigma-vector) #f 2 #f)
                                        " pixel"))
      (apply display-key-value "Mode Gains" (map (lambda (g) (number->decimal g #f 2 #f)) (vector->list g-vector))))

    (define (display-status subset)
      (display "Content-Type: text/html; charset=utf-8\r\n\r\n")
      (display "<table>\n")
      (case subset
        ((wfs-summary)
         (display-key-value "Initialized?" (wfs-initialized?))
         (display-key-value "Command" (wfs-command))
         (display-detector-summary (call-with-values wfs-window list)
                                   (wfs-pixel-frequency)
                                   (wfs-frame-frequency)
                                   (wfs-actual-frame-frequency)
                                   (wfs-frame-time)
                                   (wfs-integration-time)
                                   (wfs-exposure-time)
                                   (wfs-frame)
                                   (wfs-frames-per-integration)
                                   (wfs-integration)
                                   (wfs-integrations-per-exposure)
                                   (wfs-z-min)
                                   (wfs-z-max)
                                   (wfs-z-mean)
                                   (wfs-fwhm)
                                   (wfs-eshm)
                                   (wfs-spatial-sigma)
                                   (wfs-temporal-sigma)
                                   (wfs-ds-mean-vector)
                                   (wfs-ds-sigma-vector)
                                   (wfs-g-vector)))
        ((wfs-details)
         (display-key-value "Initialized?" (wfs-initialized?))
         (display-key-value "Command" (wfs-command))
         (display-detector-details (call-with-values wfs-window list)
                                   (wfs-pixel-frequency)
                                   (wfs-min-frame-frequency)
                                   (wfs-max-frame-frequency)
                                   (wfs-frame-frequency)
                                   (wfs-actual-frame-frequency)
                                   (wfs-frame-time)
                                   (wfs-integration-time)
                                   (wfs-exposure-time)
                                   (wfs-frame)
                                   (wfs-frames-per-integration)
                                   (wfs-integration)
                                   (wfs-integrations-per-exposure)
                                   (wfs-z-min)
                                   (wfs-z-max)
                                   (wfs-z-mean)
                                   (wfs-fwhm)
                                   (wfs-eshm)
                                   (wfs-spatial-sigma)
                                   (wfs-temporal-sigma)
                                   (wfs-ds-mean-vector)
                                   (wfs-ds-sigma-vector)))
        ((finder-summary)
         (display-key-value "Initialized?" (finder-initialized?))
         (display-key-value "Command" (finder-command))
         (display-detector-summary (call-with-values finder-window list)
                                   (finder-pixel-frequency)
                                   (finder-frame-frequency)
                                   (finder-actual-frame-frequency)
                                   (finder-frame-time)
                                   (finder-integration-time)
                                   (finder-exposure-time)
                                   (finder-frame)
                                   (finder-frames-per-integration)
                                   (finder-integration)
                                   (finder-integrations-per-exposure)
                                   (finder-z-min)
                                   (finder-z-max)
                                   (finder-z-mean)
                                   (finder-fwhm)
                                   (finder-eshm)
                                   (finder-spatial-sigma)
                                   (finder-temporal-sigma)
                                   (finder-ds-mean-vector)
                                   (finder-ds-sigma-vector)
                                   (finder-g-vector)))
        ((finder-details)
         (display-key-value "Initialized?" (finder-initialized?))
         (display-key-value "Command" (finder-command))
         (display-detector-details (call-with-values finder-window list)
                                   (finder-pixel-frequency)
                                   (finder-min-frame-frequency)
                                   (finder-max-frame-frequency)
                                   (finder-frame-frequency)
                                   (finder-actual-frame-frequency)
                                   (finder-frame-time)
                                   (finder-integration-time)
                                   (finder-exposure-time)
                                   (finder-frame)
                                   (finder-frames-per-integration)
                                   (finder-integration)
                                   (finder-integrations-per-exposure)
                                   (finder-z-min)
                                   (finder-z-max)
                                   (finder-z-mean)
                                   (finder-fwhm)
                                   (finder-eshm)
                                   (finder-spatial-sigma)
                                   (finder-temporal-sigma)
                                   (finder-ds-mean-vector)
                                   (finder-ds-sigma-vector)))
        ((instrument-summary)
         (display-key-value "Initialized?" (instrument-initialized?))
         (display-key-value "Command" (instrument-command))
         (display-detector-summary (call-with-values instrument-window list)
                                   (instrument-pixel-frequency)
                                   (instrument-frame-frequency)
                                   (instrument-actual-frame-frequency)
                                   (instrument-frame-time)
                                   (instrument-integration-time)
                                   (instrument-exposure-time)
                                   (instrument-frame)
                                   (instrument-frames-per-integration)
                                   (instrument-integration)
                                   (instrument-integrations-per-exposure)
                                   (instrument-z-min)
                                   (instrument-z-max)
                                   (instrument-z-mean)
                                   (instrument-fwhm)
                                   (instrument-eshm)
                                   (instrument-spatial-sigma)
                                   (instrument-temporal-sigma)
                                   (instrument-ds-mean-vector)
                                   (instrument-ds-sigma-vector)
                                   (instrument-g-vector)))
        ((instrument-details)
         (display-key-value "Initialized?" (instrument-initialized?))
         (display-key-value "Command" (instrument-command))
         (display-detector-details (call-with-values instrument-window list)
                                   (instrument-pixel-frequency)
                                   (instrument-min-frame-frequency)
                                   (instrument-max-frame-frequency)
                                   (instrument-frame-frequency)
                                   (instrument-actual-frame-frequency)
                                   (instrument-frame-time)
                                   (instrument-integration-time)
                                   (instrument-exposure-time)
                                   (instrument-frame)
                                   (instrument-frames-per-integration)
                                   (instrument-integration)
                                   (instrument-integrations-per-exposure)
                                   (instrument-z-min)
                                   (instrument-z-max)
                                   (instrument-z-mean)
                                   (instrument-fwhm)
                                   (instrument-eshm)
                                   (instrument-spatial-sigma)
                                   (instrument-temporal-sigma)
                                   (instrument-ds-mean-vector)
                                   (instrument-ds-sigma-vector)))

        ((housekeeping-summary)
         (when (housekeeping-initialized?)
           (display-key-value "CPU Usage"
                              (exact (round (* (housekeeping-cpu-usage) 100.0))) "%")
           (display-key-value "Disk Usage"
                              (exact (round (* (housekeeping-disk-usage) 100))) "%")))

        ((wfc-summary)
         (display-key-value "Initialized?" (wfc-initialized?))
         (display-key-value "Command" (wfc-command))
         (vector-for-each
          (lambda (key a-mean a-sigma da-mean da-sigma telescope)
            (display-key-value key
                               (emph-if-saturated a-mean (number->decimal a-mean #f 3 #t))
                               "&plusmn;"
                               (number->decimal a-sigma #f 3 #f)
                               " "
                               (number->decimal da-mean #f 3 #t)
                               "&plusmn;"
                               (number->decimal da-sigma #f 3 #f)
                               " "
                               telescope))
          #("Mode 0: Z2 Tilt"
            "Mode 1: Z3 Tilt"
            "Mode 2: Z4 Defocus"
            "Mode 3: Z5 Astigmatism"
            "Mode 4: Z6 Astigmatism"
            "Mode 5: Z9 Trefoil"
            "Mode 6: Z10 Trefoil"
            "Mode 7: Z14 Quadrifoil"
            "Mode 8: Z15 Quadrifoil")
          (wfc-a-mean-vector)
          (wfc-a-sigma-vector)
          (wfc-da-mean-vector)
          (wfc-da-sigma-vector)
          (let ((a (wfc-a-mean-vector)))
            (vector
             (cond
              ((> (vector-ref a 0) +0.2) "E")
              ((< (vector-ref a 0) -0.2) "W")
              (else ""))
             (cond
              ((> (vector-ref a 1) +0.2) "S")
              ((< (vector-ref a 1) -0.2) "N")
              (else ""))
             (cond
              ((> (vector-ref a 2) +0.2) "Up")
              ((< (vector-ref a 2) -0.2) "Down")
              (else ""))
             "" "" "" "" "" "" "" "")))
         (let ((v (wfc-tm-v-vector)))
           (display-key-value
            "TM Voltages (0-2)"
            (emph-if-saturated (vector-ref v 0) (number->decimal (vector-ref v 0) #f 2 #f))
            (emph-if-saturated (vector-ref v 1) (number->decimal (vector-ref v 1) #f 2 #f))
            (emph-if-saturated (vector-ref v 2) (number->decimal (vector-ref v 2) #f 2 #f))))
         (let ((v (wfc-dm-v-vector)))
           (do ((i 0 (+ i 8)))
               ((= i 64))
             (display-key-value (string-append "DM Voltages (" (number->string i) "-" (number->string (+ i 7)) ")")
                                (emph-if-saturated (vector-ref v (+ i 0)) (number->decimal (vector-ref v (+ i 0)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 1)) (number->decimal (vector-ref v (+ i 1)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 2)) (number->decimal (vector-ref v (+ i 2)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 3)) (number->decimal (vector-ref v (+ i 3)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 4)) (number->decimal (vector-ref v (+ i 4)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 5)) (number->decimal (vector-ref v (+ i 5)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 6)) (number->decimal (vector-ref v (+ i 6)) #f 2 #f))
                                (emph-if-saturated (vector-ref v (+ i 7)) (number->decimal (vector-ref v (+ i 7)) #f 2 #f))))))

        ((lamp-summary)
         (display-key-value "Initialized?" (lamp-initialized?))
         (display-key-value "Command" (lamp-command))
         (display-key-value "State" (if (lamp-state) "On" "Off"))))

      (display "</table>\n"))))
